import com.supermap.blockchain.sdk.SmChain;
import com.supermap.blockchain.sdk.SmChaincode;
import com.supermap.blockchain.sdk.SmTransaction;
import org.hyperledger.fabric.sdk.TransactionRequest;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;

import java.io.File;

public class Benchmark {
    private SmChain smChain;
    private String chaincodeName;
    private String functionName;
    private String[] argsStr;
    private byte[][] argsBytes;
    private long txCount = 1;

    public Benchmark(String functionName, File networkFile) {
        smChain = SmChain.getChain(functionName, networkFile);
    }

    double calcWriteStrTPS() {
        SmTransaction smTransaction = smChain.getTransaction();
        String key = argsStr[0];
        String value = argsStr[1];
        long startTime = System.currentTimeMillis();
        System.out.println(startTime);
        for (int i = 0; i < txCount; i++) {
            argsStr[0] = key + i;
            argsStr[1] = value + i;
            String result = smTransaction.invokeByString(chaincodeName, functionName, argsStr);
//            System.out.println(result + "-" + i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println(endTime);
        return (endTime - startTime) / 1000.0;
    }


    double calcReadTPS() {
        SmTransaction smTransaction = smChain.getTransaction();
        String key = argsStr[0];
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < txCount; i++) {
            argsStr[0] = key + i;
            String result = smTransaction.queryByString(chaincodeName, functionName, argsStr);
            System.out.println(result + "-" + i);
        }
        long endTime = System.currentTimeMillis();
        return  (endTime - startTime) / 1000.0;
    }

    double calcWriteByteTPS() throws ParseException {
        SmTransaction smTransaction = smChain.getTransaction();
        String key = String.valueOf(argsBytes[0]);
        long startTime = System.currentTimeMillis();
//        System.out.println(startTime);
        for (int i = 0; i < txCount; i++) {
            argsBytes[0] = (key + i).getBytes();
            Geometry geometry = new WKBReader().read(argsBytes[1]);
//            System.out.println(geometry.toString());
            String result = smTransaction.invokeByByte(chaincodeName, functionName, argsBytes);
//            System.out.println(result + "-" + i);
        }
        long endTime = System.currentTimeMillis();
//        System.out.println(endTime);
        return (endTime - startTime) / 1000.0;
    }

    double calcReadByteTPS() throws ParseException {
        SmTransaction smTransaction = smChain.getTransaction();
        String key = String.valueOf(argsBytes[0]);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < txCount; i++) {
            key = (key + i);
            byte[][] result = smTransaction.queryByByte(chaincodeName, functionName, new byte[][]{key.getBytes()});
//            System.out.println(String.valueOf(result[0]));
//            Geometry geometry = new WKBReader().read(result[0]);
//            System.out.println(geometry.toString());
//            System.out.println(result + "-" + i);
        }
        long endTime = System.currentTimeMillis();
        return  (endTime - startTime) / 1000.0;
    }

    void installChaincode() {
        SmChaincode smChaincode = smChain.getChaincode();
        String chaincodeVersion = "1.0";
        String chaincodePath = "/home/cy/Documents/repositories/gitee.com/FabricBenchmark/src/main/resources/Common";
        String endosermentPolicyPath = this.getClass().getResource("/chaincode-endorsement-policy.yaml").getPath();
        if (smChaincode.install(chaincodeName, chaincodeVersion, chaincodePath, TransactionRequest.Type.JAVA)) {
            smChaincode.instantiate(chaincodeName, chaincodeVersion, chaincodePath, new File(endosermentPolicyPath), TransactionRequest.Type.JAVA);
        }
    }

    public String getChaincodeName() {
        return chaincodeName;
    }

    public void setChaincodeName(String chaincodeName) {
        this.chaincodeName = chaincodeName;
    }

    public String getFunctionName() {
        return functionName;
    }

    public void setFunctionName(String functionName) {
        this.functionName = functionName;
    }

    public String[] getArgsStr() {
        return argsStr;
    }

    public void setArgsStr(String[] argsStr) {
        this.argsStr = argsStr;
    }
    
    public void setArgsBytes(byte[][] argsBytes) {
        this.argsBytes = argsBytes;
    }

    public long getTxCount() {
        return txCount;
    }

    public void setTxCount(long txCount) {
        this.txCount = txCount;
    }

}
